home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / Main.bin / Polygon.java < prev    next >
Text File  |  1998-09-22  |  9KB  |  286 lines

  1. /*
  2.  * @(#)Polygon.java    1.18 98/07/01
  3.  *
  4.  * Copyright 1995-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  * 
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14. package java.awt;
  15.  
  16. /**
  17.  * The <code>Polygon</code> class encapsulates a description of a 
  18.  * closed, two-dimensional region within a coordinate space. This 
  19.  * region is bounded by an arbitrary number of line segments, each of 
  20.  * which is one side of the polygon. Internally, a polygon 
  21.  * comprises of a list of (<i>x</i>, <i>y</i>) coordinate pairs, 
  22.  * where each pair defines a <i>vertex</i> of the polygon, and two 
  23.  * successive pairs are the endpoints of a line that is a side of the 
  24.  * polygon. The first and final pairs of (<i>x</i>, <i>y</i>) 
  25.  * points are joined by a line segment that closes the polygon.
  26.  *
  27.  * @version     1.18, 07/01/98
  28.  * @author     Sami Shaio
  29.  * @author      Herb Jellinek
  30.  * @since       JDK1.0
  31.  */
  32. public class Polygon implements Shape, java.io.Serializable {
  33.  
  34.     /**
  35.      * The total number of points.
  36.      * @since JDK1.0
  37.      */
  38.     public int npoints = 0;
  39.  
  40.     /**
  41.      * The array of <i>x</i> coordinates. 
  42.      * @since   JDK1.0
  43.      */
  44.     public int xpoints[] = new int[4];
  45.  
  46.     /**
  47.      * The array of <i>y</i> coordinates. 
  48.      * @since   JDK1.0
  49.      */
  50.     public int ypoints[] = new int[4];
  51.     
  52.     /*
  53.      * Bounds of the polygon.
  54.      */
  55.     protected Rectangle bounds = null;
  56.     
  57.     /* 
  58.      * JDK 1.1 serialVersionUID 
  59.      */
  60.     private static final long serialVersionUID = -6460061437900069969L;
  61.  
  62.     /**
  63.      * Creates an empty polygon.
  64.      * @since JDK1.0
  65.      */
  66.     public Polygon() {
  67.     }
  68.  
  69.     /**
  70.      * Constructs and initializes a polygon from the specified 
  71.      * parameters. 
  72.      * @param      xpoints   an array of <i>x</i> coordinates.
  73.      * @param      ypoints   an array of <i>y</i> coordinates.
  74.      * @param      npoints   the total number of points in the polygon.
  75.      * @exception  NegativeArraySizeException if the value of
  76.      *                       <code>npoints</code> is negative.
  77.      * @since      JDK1.0
  78.      */
  79.     public Polygon(int xpoints[], int ypoints[], int npoints) {
  80.     this.npoints = npoints;
  81.     this.xpoints = new int[npoints];
  82.     this.ypoints = new int[npoints];
  83.     System.arraycopy(xpoints, 0, this.xpoints, 0, npoints);
  84.     System.arraycopy(ypoints, 0, this.ypoints, 0, npoints);    
  85.     }
  86.     
  87.     /**
  88.      * Translates the vertices by <code>deltaX</code> along the 
  89.      * <i>x</i> axis and by <code>deltaY</code> along the 
  90.      * <i>y</i> axis.
  91.      * @param deltaX the amount to translate along the <i>x</i> axis
  92.      * @param deltaY the amount to translate along the <i>y</i> axis
  93.      * @since JDK1.1
  94.      */
  95.     public void translate(int deltaX, int deltaY) {
  96.     for (int i = 0; i < npoints; i++) {
  97.         xpoints[i] += deltaX;
  98.         ypoints[i] += deltaY;
  99.     }
  100.     if (bounds != null) {
  101.         bounds.translate(deltaX, deltaY);
  102.     }
  103.     }
  104.  
  105.     /*
  106.      * Calculate the bounding box of the points passed to the constructor.
  107.      * Sets 'bounds' to the result.
  108.      */
  109.     void calculateBounds(int xpoints[], int ypoints[], int npoints) {
  110.     int boundsMinX = Integer.MAX_VALUE;
  111.     int boundsMinY = Integer.MAX_VALUE;
  112.     int boundsMaxX = Integer.MIN_VALUE;
  113.     int boundsMaxY = Integer.MIN_VALUE;
  114.     
  115.     for (int i = 0; i < npoints; i++) {
  116.         int x = xpoints[i];
  117.         boundsMinX = Math.min(boundsMinX, x);
  118.         boundsMaxX = Math.max(boundsMaxX, x);
  119.         int y = ypoints[i];
  120.         boundsMinY = Math.min(boundsMinY, y);
  121.         boundsMaxY = Math.max(boundsMaxY, y);
  122.     }
  123.     bounds = new Rectangle(boundsMinX, boundsMinY,
  124.                    boundsMaxX - boundsMinX,
  125.                    boundsMaxY - boundsMinY);
  126.     }
  127.  
  128.     /*
  129.      * Update the bounding box to fit the point x, y.
  130.      */
  131.     void updateBounds(int x, int y) {
  132.     if (x < bounds.x) {
  133.         bounds.width = bounds.width + (bounds.x - x);
  134.         bounds.x = x;
  135.     }
  136.     else {
  137.         bounds.width = Math.max(bounds.width, x - bounds.x);
  138.         // bounds.x = bounds.x;
  139.     }
  140.  
  141.     if (y < bounds.y) {
  142.         bounds.height = bounds.height + (bounds.y - y);
  143.         bounds.y = y;
  144.     }
  145.     else {
  146.         bounds.height = Math.max(bounds.height, y - bounds.y);
  147.         // bounds.y = bounds.y;
  148.     }
  149.     }    
  150.  
  151.     /**
  152.      * Appends a point to this polygon. 
  153.      * <p>
  154.      * If an operation that calculates the bounding box of this polygon
  155.      * has already been performed, such as <code>getBounds</code> 
  156.      * or <code>contains</code>, then this method updates the bounding box. 
  157.      * @param       x   the <i>x</i> coordinate of the point.
  158.      * @param       y   the <i>y</i> coordinate of the point.
  159.      * @see         java.awt.Polygon#getBounds
  160.      * @see         java.awt.Polygon#contains
  161.      * @since       JDK1.0
  162.      */
  163.     public void addPoint(int x, int y) {
  164.     if (npoints == xpoints.length) {
  165.         int tmp[];
  166.  
  167.         tmp = new int[npoints * 2];
  168.         System.arraycopy(xpoints, 0, tmp, 0, npoints);
  169.         xpoints = tmp;
  170.  
  171.         tmp = new int[npoints * 2];
  172.         System.arraycopy(ypoints, 0, tmp, 0, npoints);
  173.         ypoints = tmp;
  174.     }
  175.     xpoints[npoints] = x;
  176.     ypoints[npoints] = y;
  177.     npoints++;
  178.     if (bounds != null) {
  179.         updateBounds(x, y);
  180.     }
  181.     }
  182.  
  183.     /**
  184.      * Gets the bounding box of this polygon. The bounding box is the
  185.      * smallest rectangle whose sides are parallel to the <i>x</i> and
  186.      * <i>y</i> axes of the coordinate space, and that can completely
  187.      * contain the polygon.
  188.      * @return      a rectangle that defines the bounds of this polygon.
  189.      * @since       JDK1.1
  190.      */
  191.     public Rectangle getBounds() {
  192.     return getBoundingBox();
  193.     }
  194.  
  195.     /**
  196.      * @deprecated As of JDK version 1.1,
  197.      * replaced by <code>getBounds()</code>.
  198.      */
  199.     public Rectangle getBoundingBox() {
  200.     if (bounds == null) {
  201.         calculateBounds(xpoints, ypoints, npoints);
  202.     }
  203.     return bounds;
  204.     }
  205.  
  206.     /**
  207.      * Determines whether the specified point is inside the Polygon.
  208.      * Uses an even-odd insideness rule (also known as an alternating
  209.      * rule).
  210.      * @param p the point to be tested
  211.      */
  212.     public boolean contains(Point p) {
  213.     return contains(p.x, p.y);
  214.     }
  215.  
  216.     /**
  217.      * Determines whether the specified point is contained by this polygon.   
  218.      * <p>
  219.      * (The <code>contains</code> method is based on code by 
  220.      * Hanpeter van Vliet [hvvliet@inter.nl.net].) 
  221.      * @param      x  the <i>x</i> coordinate of the point to be tested.
  222.      * @param      y  the <i>y</i> coordinate of the point to be tested.
  223.      * @return     <code>true</code> if the point (<i>x</i>, <i>y</i>) 
  224.      *                       is contained by this polygon; 
  225.      *                       <code>false</code> otherwise.
  226.      * @since      JDK1.1
  227.      */
  228.     public boolean contains(int x, int y) {
  229.     return inside(x, y);
  230.     }
  231.  
  232.     /**
  233.      * @deprecated As of JDK version 1.1,
  234.      * replaced by <code>contains(int, int)</code>.
  235.      */
  236.     public boolean inside(int x, int y) {
  237.         if (getBoundingBox().inside(x, y)) {
  238.             int hits = 0;
  239.             int ySave = 0;
  240.  
  241.             // Find a vertex that's not on the halfline
  242.             int i = 0;
  243.             while (i < npoints && ypoints[i] == y) {
  244.                 i++;
  245.         }
  246.  
  247.             // Walk the edges of the polygon
  248.             for (int n = 0; n < npoints; n++) {
  249.                 int j = (i + 1) % npoints;
  250.  
  251.                 int dx = xpoints[j] - xpoints[i];
  252.                 int dy = ypoints[j] - ypoints[i];
  253.  
  254.                 // Ignore horizontal edges completely
  255.                 if (dy != 0) {
  256.                     // Check to see if the edge intersects
  257.                     // the horizontal halfline through (x, y)
  258.                     int rx = x - xpoints[i];
  259.                     int ry = y - ypoints[i];
  260.  
  261.                     // Deal with edges starting or ending on the halfline
  262.                     if (ypoints[j] == y && xpoints[j] >= x) {
  263.                         ySave = ypoints[i];
  264.             }
  265.                     if (ypoints[i] == y && xpoints[i] >= x) {
  266.                         if ((ySave > y) != (ypoints[j] > y)) {
  267.                 hits--;
  268.             }
  269.             }
  270.  
  271.                     // Tally intersections with halfline
  272.                     float s = (float)ry / (float)dy;
  273.                     if (s >= 0.0 && s <= 1.0 && (s * dx) >= rx) {
  274.                         hits++;
  275.             }
  276.                 }
  277.                 i = j;
  278.             }
  279.  
  280.             // Inside if number of intersections odd
  281.             return (hits % 2) != 0;
  282.         }
  283.         return false;
  284.     }
  285. }
  286.